[CDK] CloudFrontでCORSヘッダを設定する
吉川@広島です。
今回はCDKでCloudFrontにCORSレスポンスヘッダを設定する方法を紹介します。
環境
- aws-cdk-lib 2.46.0
- constructs 10.1.43
コード
CloudFront ResponseHeadersPolicyを利用することで比較的簡単に設定できます。
import * as cdk from "aws-cdk-lib" import { Construct } from "constructs" export class CloudfrontStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props) const webBucket = new cdk.aws_s3.Bucket(this, "webBucket", { removalPolicy: cdk.RemovalPolicy.DESTROY, }) const originAccessIdentity = new cdk.aws_cloudfront.OriginAccessIdentity( this, "originAccessIdentity" ) const distribution = new cdk.aws_cloudfront.Distribution( this, "distribution", { defaultRootObject: "index.html", errorResponses: [ { httpStatus: 404, responseHttpStatus: 200, responsePagePath: "/index.html", ttl: cdk.Duration.seconds(0), }, { httpStatus: 403, responseHttpStatus: 200, responsePagePath: "/index.html", ttl: cdk.Duration.seconds(0), }, ], defaultBehavior: { allowedMethods: cdk.aws_cloudfront.AllowedMethods.ALLOW_GET_HEAD, cachePolicy: cdk.aws_cloudfront.CachePolicy.CACHING_DISABLED, viewerProtocolPolicy: cdk.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, origin: new cdk.aws_cloudfront_origins.S3Origin(webBucket, { originAccessIdentity, }), responseHeadersPolicy: new cdk.aws_cloudfront.ResponseHeadersPolicy( this, "responseHeadersPolicy", { corsBehavior: { accessControlAllowOrigins: ["https://example.com"], accessControlAllowHeaders: ["*"], accessControlAllowMethods: ["ALL"], accessControlAllowCredentials: false, originOverride: true, }, } ), }, } ) new cdk.aws_s3_deployment.BucketDeployment(this, "webDeploy", { sources: [ cdk.aws_s3_deployment.Source.data( "/index.html", "<html><body><h1>Hello World</h1></body></html>" ), ], destinationBucket: webBucket, distribution: distribution, distributionPaths: ["/*"], }) } }
ポイントとなるのは見たまんまで、
responseHeadersPolicy: new cdk.aws_cloudfront.ResponseHeadersPolicy( this, "responseHeadersPolicy", { corsBehavior: { accessControlAllowOrigins: ["https://example.com"], accessControlAllowHeaders: ["*"], accessControlAllowMethods: ["ALL"], accessControlAllowCredentials: false, originOverride: true, }, } ),
の箇所になります。
やってみる
それでは上記をデプロイします。
npx cdk deploy
curlコマンドで動作確認します。
curl -X OPTIONS -H "Origin: https://example.com" -H "Access-Control-Request-Method: GET" --dump-header - https://xxxxxxxxxxxxx.cloudfront.net
HTTP/2 200 content-type: text/html content-length: 46 date: Sun, 19 Feb 2023 09:42:46 GMT last-modified: Sun, 19 Feb 2023 09:28:50 GMT etag: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" x-amz-server-side-encryption: AES256 accept-ranges: bytes server: AmazonS3 x-cache: Error from cloudfront via: 1.1 xxxxxxxxxxxxxxxxxx.cloudfront.net (CloudFront) x-amz-cf-pop: KIX50-P3 x-amz-cf-id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx access-control-allow-origin: https://example.com vary: Origin <html><body><h1>Hello World</h1></body></html>
access-control-allow-originが返ってくることが確認できました。
ハマった点
当初 accessControlAllowMethods
に誤った値( ALL
ではなく *
)を設定していたせいで、
Stack Deployments Failed: Error: The stack named IacStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Internal error reported from downstream service during operation 'AWS::CloudFront::ResponseHeadersPolicy'.
というエラーが出ました。どのプロパティがNGなのか分からないメッセージで少しハマったのですが、ググった過程で類似のエラーに困っているIssueを発見し、
「この場合はCloudFormationでは内部エラーとしか出ないようだ。UIでは詳細なエラーが見れる」(要約)とのことだったので、マネコンから手動でリソース設定を試したところ間違いに気づくことができました。
このようにCloudFormation/CDKというかIaCツールはたまにエラーメッセージが分かりづらいことがある気がします。その際はIaC操作のみで原因究明することに固執せずマネコンからリソースを作ってデバッグしてみましょう。
参考
- Issue creating AWS::CloudFront::ResponseHeadersPolicy · Issue #1156 · aws-cloudformation/cloudformation-coverage-roadmap
- [UPDATE] Amazon CloudFrontでResponse headers policiesがサポートされました! | DevelopersIO
- L@EとCF2が不要に?!CloudFront単体でレスポンスヘッダーが設定できるようになりました | DevelopersIO
- cURL でレスポンスヘッダを表示する - Qiita
- CloudFrontでCORS設定をするための3つのポリシーについて